﻿// ***********************************************************************
// Project			: Micua
// Assembly         : Micua.DAL
// Author           : iceStone
// Created          : 2013-11-18 11:54
//
// Last Modified By : iceStone
// Last Modified On : 2013-11-18 11:58
// ***********************************************************************
// <copyright file="BaseRepository.cs" company="Wedn.Net">
//     Copyright (c) Wedn.Net. All rights reserved.
// </copyright>
// <summary>数据访问层基类</summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Micua.IDAL;
using Micua.Model;

namespace Micua.DAL
{
    /// <summary>
    /// 数据库访问基类
    /// </summary>
    /// <remarks>
    ///  2013-11-18 19:05 Created By iceStone
    /// </remarks>
    /// <typeparam name="TEntity">数据实体类型</typeparam>
    public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, IEntity<TEntity>
    {
        /// <summary>
        /// 数据库实体操作上下文(线程内实例唯一)
        /// </summary>
        /// <value>The _DB context.</value>
        private static DbContext DbContext { get { return Factory.GetCurrentDbContext(); } }
        //private readonly DbContext _dbContext = Factory.GetCurrentDbContext();
        //DataModelContainer dbContext = new DataModelContainer();
        /// <summary>
        /// 数据集
        /// </summary>
        /// <value>The database set.</value>
        public DbSet<TEntity> DbSet { get { return DbContext.Set<TEntity>(); } }
        /// <summary>
        /// 向数据库中插入一条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual TEntity Insert(TEntity entity)
        {
            DbContext.Set<TEntity>().Add(entity);
            //_dbContext.Entry<T>(entity).State = EntityState.Added;
            //_dbContext.SaveChanges();
            return entity;
        }

        /// <summary>
        /// 向数据库中插入一条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">要插入的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>当前实体</returns>
        public virtual TEntity Insert(TEntity entity, bool commit)
        {
            DbContext.Set<TEntity>().Add(entity);
            if (commit)
                DbContext.SaveChanges();
            return entity;
        }

        /// <summary>
        /// 向数据库中插入多条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entitys">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual IList<TEntity> Insert(params TEntity[] entitys)
        {
            foreach (var entity in entitys)
            {
                DbContext.Set<TEntity>().Add(entity);
                //_dbContext.Entry<T>(entity).State = EntityState.Added;
            }
            //_dbContext.SaveChanges();
            return entitys;
        }

        /// <summary>
        /// 向数据库中插入多条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="entitys">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual IList<TEntity> Insert(bool commit, params TEntity[] entitys)
        {
            foreach (var entity in entitys)
            {
                DbContext.Set<TEntity>().Add(entity);
            }
            if (commit)
                DbContext.SaveChanges();
            return entitys;
        }

        /// <summary>
        /// 删除数据库中的一条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">要删除的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(TEntity entity)
        {
            //_dbContext.Set<T>().Remove(entity);
            DbContext.Entry(entity).State = EntityState.Deleted;
            //return _dbContext.SaveChanges();
            return 1;
        }

        /// <summary>
        /// 删除数据库中的一条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">要删除的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(TEntity entity, bool commit)
        {
            DbContext.Entry(entity).State = EntityState.Deleted;
            return commit ? DbContext.SaveChanges() : 1;
        }

        /// <summary>
        /// 批量删除数据库中多条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="ids">要删除的实体Id</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(params int[] ids)
        {
            foreach (int id in ids)
            {
                DbContext.Set<TEntity>().Remove(DbContext.Set<TEntity>().Find(id));
            }
            //return _dbContext.SaveChanges();
            return ids.Length;
        }

        /// <summary>
        /// 批量删除数据库中多条数据
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="ids">要删除的实体Id</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(bool commit, params int[] ids)
        {
            foreach (int id in ids)
            {
                DbContext.Set<TEntity>().Remove(DbContext.Set<TEntity>().Find(id));
            }
            return commit ? DbContext.SaveChanges() : ids.Length;
        }

        /// <summary>
        /// 更新数据库中的一个实体
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(TEntity entity)
        {
            DbContext.Entry(entity).State = EntityState.Modified;
            //return _dbContext.SaveChanges();
            return 1;
        }

        /// <summary>
        /// 更新数据库中的一个实体
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entity">更新的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(TEntity entity, bool commit)
        {
            DbContext.Entry(entity).State = EntityState.Modified;
            return commit ? DbContext.SaveChanges() : 1;
        }

        /// <summary>
        /// 更新数据库中的多个实体
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="entitys">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(params TEntity[] entitys)
        {
            foreach (var entity in entitys)
            {
                DbContext.Entry(entity).State = EntityState.Modified;
            }
            //return _dbContext.SaveChanges();
            return entitys.Count();
        }

        /// <summary>
        /// 更新数据库中的多个实体
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="entitys">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(bool commit, params TEntity[] entitys)
        {
            foreach (var entity in entitys)
            {
                DbContext.Entry(entity).State = EntityState.Modified;
            }
            //return _dbContext.SaveChanges();
            return commit ? DbContext.SaveChanges() : entitys.Count();
        }

        /// <summary>
        /// 根据传入委托查询出存在条数
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <returns>存在条数</returns>
        public virtual int QueryCount()
        {
            return DbContext.Set<TEntity>().Count();
        }

        /// <summary>
        /// 根据传入委托查询出存在条数
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="predicate">筛选条件表达式</param>
        /// <returns>存在条数</returns>
        public virtual int QueryCount(Expression<Func<TEntity, bool>> predicate)
        {
            return DbContext.Set<TEntity>().Count(predicate);
        }

        /// <summary>
        /// 根据传入委托筛选出对应的单个数据实体
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="predicate">筛选条件表达式</param>
        /// <returns>查询到单个数据实体</returns>
        public virtual TEntity QuerySingle(Expression<Func<TEntity, bool>> predicate)
        {
            return DbContext.Set<TEntity>().FirstOrDefault(predicate);
        }

        /// <summary>
        /// 选取数据库中的实体集合
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <returns>实体集合</returns>
        public virtual IQueryable<TEntity> Query()
        {
            //return _dbContext.Set<T>().Where<T>(predicate).AsQueryable<T>();
            return DbContext.Set<TEntity>().AsQueryable();
        }

        /// <summary>
        /// 选取数据库中的实体集合
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="predicate">筛选条件</param>
        /// <returns>实体集合</returns>
        public virtual IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate)
        {
            //return _dbContext.Set<T>().Where<T>(predicate).AsQueryable<T>();
            return DbContext.Set<TEntity>().Where(predicate).AsQueryable();
        }

        /// <summary>
        /// 分页选取数据库中的实体集合
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <typeparam name="TField">排序字段类型</typeparam>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="totalCount">总记录数</param>
        /// <param name="predicate">筛选条件</param>
        /// <param name="keySelector">排序条件</param>
        /// <param name="isDesc">是否降序排列</param>
        /// <returns>实体集合</returns>
        public virtual IQueryable<TEntity> QueryPage<TField>(int pageIndex, int pageSize, out int totalCount, Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TField>> keySelector, bool isDesc)
        {
            totalCount = DbContext.Set<TEntity>().Where<TEntity>(predicate).Count<TEntity>();
            if (isDesc)
                return DbContext.Set<TEntity>()
                        .Where<TEntity>(predicate)
                        .OrderByDescending<TEntity, TField>(keySelector)
                        .Skip<TEntity>(pageSize * (pageIndex - 1))
                        .Take<TEntity>(pageSize)
                        .AsQueryable<TEntity>();
            return DbContext.Set<TEntity>()
                    .Where<TEntity>(predicate)
                    .OrderBy<TEntity, TField>(keySelector)
                    .Skip<TEntity>(pageSize * (pageIndex - 1))
                    .Take<TEntity>(pageSize)
                    .AsQueryable<TEntity>();
        }

        /// <summary>
        /// 执行一个非查询的T-SQL语句，返回受影响行数
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>受影响行数</returns>
        public virtual int ExcuteNonQuery(string sql, params object[] parameters)
        {
            return DbContext.Database.ExecuteSqlCommand(sql, parameters);
        }

        /// <summary>
        /// 执行一个原始SQL查询，返回泛型类型迭代器
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>泛型类型迭代器</returns>
        public virtual IEnumerable<TEntity> SqlQuery(string sql, params object[] parameters)
        {
            return DbContext.Database.SqlQuery<TEntity>(sql, parameters);
        }

        /// <summary>
        /// 保存数据库的改变状态
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        /// <returns>受影响行数</returns>
        public virtual int SaveChanges()
        {
            return DbContext.SaveChanges();
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <remarks>
        ///  2013-11-18 19:05 Created By iceStone
        /// </remarks>
        public void Dispose()
        {
            DbContext.Dispose();
        }
    }
}
